package day07.utils;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class JDBCUtils {
    public static Connection getConnection(String url, String user, String password) {
        try {
            return DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public static void close(Connection conn, Statement statement, ResultSet resultSet) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static int update(Connection connection, String sql, Object... args) {
        return updateOrInsertOrDelete(connection, sql, args);
    }

    private static int updateOrInsertOrDelete(Connection connection, String sql, Object[] args) {
        PreparedStatement preparedStatement = null;
        try {
            // 检查连接是否有效
            if (connection == null || connection.isClosed()) {
                throw new SQLException("Database connection is not available");
            }

            preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }
            return preparedStatement.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtils.close(connection, preparedStatement, null);
        }
    }

    public static int insert(Connection connection, String sql, Object... args) {
        return updateOrInsertOrDelete(connection, sql, args);
    }

    public static int delete(Connection connection, String sql, Object... args) {
        return updateOrInsertOrDelete(connection, sql, args);
    }

    public static <T> List<T> query(Connection connection, String sql, Class<T> clazz, Object... args) {
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {

            List<T> result = new ArrayList<>();
            preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                T t = clazz.getConstructor().newInstance();
                for (Field declaredField : clazz.getDeclaredFields()) {
                    declaredField.setAccessible(true);
                    declaredField.set(t, resultSet.getObject(declaredField.getName()));
                }
                result.add(t);
            }
            return result;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtils.close(connection, preparedStatement, resultSet);
        }
    }

    public static <T> T queryById(Connection connection, String sql, Class<T> clazz, Object... args) {
        List<T> query = query(connection, sql, clazz, args);
        return query.isEmpty() ? null : query.getFirst();
    }

}
